Ejercicio: OBIA en GRASS GIS
Ejercicio: Clasificación supervisada basada en objetos con datos SPOT
Contenidos
- Mejoramiento del contraste (ecualización del histograma)
- Calcular índices espectrales y texturas de GLCM
- Segmentación manual (ensayo y error)
- Segmentación con USPO
- Cómputo de las estadísticas de los segmentos
- Colecta y etiquetado de datos de entrenamiento y validación
- Clasificación supervisada por Machine Learning
- Validación
Datos para el ejercicio
- SPOT 6
- VIS - NIR (6 m)
- PAN (1.5 m)
- Datos corregidos y fusionados
Descargar los datos SPOT desde el aula virtual y mover a la carpeta $HOME/gisdata
import os
import subprocess
import sys
# Ask GRASS GIS where its Python packages are to be able to start it from the notebook
sys.path.append(
subprocess.check_output(["grass", "--config", "python_path"], text=True).strip()
)
# Importar los paquetes python de GRASS
import grass.script as gs
import grass.jupyter as gj
# Iniciar GRASS
session = gj.init(grassdata, location, mapset)Tareas
- Crear un mapset
obia_spoten el locationposgar2007_4_cbae importar la imagen SPOT desde la GUI forzando la resolución a 1.5m- Alinear la región a la extensión y resolución de alguna de las bandas importadas
- Mostrar la combinación RGB color natural (1: azul, 2: verde, 3: rojo, 4: NIR)
- Hacer una ecualización de histograma para mejorar el contraste de visualización
Importar datos y visualizar
Crear mapset
Importar bandas multi-espectrales
Importar banda pancromática
Alinear región y guardar la configuración
Establecer grey como paleta de colores para bandas RGB
Mostrar composición RGB
Ecualización de colores
Composición RGB 321 color natural - SPOT 6)
Hay valores nulos?
Valores nulos en una banda
Valores nulos en varias bandas
Si hubiera valores nulos, se deben rellenar antes de comenzar (fa?, exclamation-triangle text-orange)
Índices espectrales y texturas GLCM
Estimar NDVI
Instalar extensión i.wi y estimar NDWI
Establecer la paleta de colores ndwi
Estimar medidas de textura: IDM y ASM
Establecer paleta grey para bandas de textura
Visualizar
Índices espectrales y texturas GLCM a partir de bandas SPOT
Sobre qué banda calculamos las texturas?
Si no contamos con una banda pancromática, podemos crearla promediando las bandas visibles
Segmentación
Búsqueda de umbrales de sub y sobre-segmentación
Crear grupo con las bandas únicamente
Definir una región más pequeña y salvarla
Ejecutar una segmentación con umbral pequeño
Ejecutar una segmentación con umbral más grande
Sobre-segmentado
Sub-segmentado
Tarea
Se animan a probar con otros valores y en otras regiones?
Segmentación
Búsqueda automática de umbrales por optimización
- Altamente intensivo para un área grande y muchas combinaciones de parámetros
- Limitar el tamaño de la región computacional
- Limitar el rango de los parámetros
- Crear superpixels para usarlos como semillas
- Cortar la imagen en tiles (i.cutlines) y paralelizar la USPO
Generación de semillas
- También puede utilizarse para la segmentación real
- Muy rápido para reagrupar pequeñas cantidades de píxeles similares
- Usar para reducir el número de píxeles en un factor de 4-5 y acelerar i.segment.uspo
- Baja compactación para mantener la separación espectral
USPO con superpixels como semillas
Instalar la extensión
Ejecutar i.superpixels.slic con bajo valor de compactación
RGB y resultado de la ejecución de i.superpixels.slic
Cuántas semillas se generaron? Qué factor de reducción se consigue en comparación a usar todos los pixeles?
USPO con superpixels como semillas
Instalar las extensiones
Ejecutar la segmentación con optimización
Convertir el “mejor” resultado a vector
Zoom al resultado de ejecutar la segmentación con USPO
Cuántos segmentos obtuvieron?
Dar una mirada a v.info
Estadísticas: i.segment.stats
Instalar las extensiones
Ejecutar i.segment.stats
# extract stats for segments
i.segment.stats \
map=segs_obia_subset_rank1 \
rasters=SPOT_20180621_ASM,SPOT_20180621_IDM,SPOT_20180621_NDVI,SPOT_20180621_NDWI,SPOT_20180621_PAN \
raster_statistics=mean,stddev \
area_measures=area,perimeter,compact_circle,compact_square \
vectormap=segs_stats \
processes=4Tabla de atributos con las estadísticas estimadas para cada objeto
Datos de entrenamiento
Info básica de los puntos de entrenamiento provistos
Copiarse el vector al mapset obia_spot
Cuántos puntos de cada clase tenemos?
Seleccionar segmentos sobre los cuales tenemos puntos de entrenamiento
Cuántos segmentos contienen puntos de entrenamiento?
Selección de segmentos con puntos de entrenamiento
Datos de entrenamiento
Agregar columna al vector con los segmentos para luego transferir la clase
Asignar la clase de los puntos a los segmentos
Cuántos segmentos de cada clase tenemos?
Datos de entrenamiento
Asignación de colores interactivamente
- Ir agregando valores
- Seleccionar colores
- Previsualizar
- Guardar la paleta creada como obia_urban para reusar posteriormente
Selección y etiquetado de datos de entrenamiento y validación
- Ejecutar una clasificación no supervisada con 10 clases
- Extraer una x cantidad de puntos por clase (r.sample.category)
- Etiquetar los puntos manualmente
- Usar puntos para transferir las etiquetas a los segmentos como ya vimos
# Unsupervised classification
i.group group=spot_all \
input=SPOT_20180621_ASM,SPOT_20180621_IDM,SPOT_20180621_NDVI,SPOT_20180621_NDWI,SPOT_20180621_PAN,SPOT_20180621_PANSHARP.1,SPOT_20180621_PANSHARP.2,SPOT_20180621_PANSHARP.3,SPOT_20180621_PANSHARP.4
i.cluster group=spot_all signaturefile=sig classes=10
i.maxlik group=spot_all signaturefile=sig output=uns_clas
# install extension
g.extension r.sample.category
# get n points per class
r.sample.category input=uns_clas \
output=uns_clas_points \
npoints=150
# Manually label pointsClasificación con Machine learning
Instalar la extensión
Ejecutar la clasificación
# run classification
v.class.mlR -nf \
segments_map=segs_stats \
training_map=train_segments \
train_class_column=class \
output_class_column=class_rf \
classified_map=classification \
raster_segments_map=segs_obia_subset_rank1 \
classifier=rf \
folds=5 partitions=10 tunelength=10 \
weighting_modes=smv \
weighting_metric=accuracy \
output_model_file=model \
variable_importance_file=var_imp.txt \
accuracy_file=accuracy.csv \
classification_results=all_results.csv \
model_details=classifier_runs.txt \
r_script_file=Rscript_mlR.R \
processes=4Establecer paleta de colores
Resultado de la clasificación supervisada con Machine Learning basada en objetos
El proceso de clasificación usualmente conlleva una serie de iteraciones que implican selección de variables más importantes, búsqueda de más/mejores datos de entrenamiento y validación
Validación
- Se usan datos independientes para validar las clasificaciones
- Se construye una matriz de confusión que permite visualizar los errores por clase en los elementos que están fuera de la diagonal
- Se estiman varias medidas relacionadas a la precisión, ej.: overall accuracy y kappa
Validación
Distintas opciones: 1. Generar un nuevo set de puntos y etiquetarlos 2. Separar el set de puntos etiquetados en train y test de antemano
Validación en GRASS GIS
- Necesita mapas raster como input
- Transformar los segmentos de validación a formato raster usando la columna
classcomo fuente de valores para los pixeles
- Transformar los segmentos de validación a formato raster usando la columna
Tarea
Generar un set de validación de al menos 50 segmentos y ejecutar r.kappa
Validación en GRASS GIS
Una vez creado el vector de segmentos con etiquetas testing, convertirlo a formato raster
Ejecutar r.kappa
Alternativamente, podemos separar el set de puntos etiquetados en train y test. Vamos a R.
Cargar librerías
Leer el vector desde GRASS
Crear set de validación
Separar set de entrenamiento
Escribir los vectores a GRASS nuevamente
Tarea
Ejecutar nuevamente la clasificación usando sólo el vector train
Agregar columna al vector test
Obtener las clases predichas para los segmentos de validación
Validación en R
Leer el vector test que tiene la clase predicha
Cargar la librería caret y obtener la matriz de confusión
# confusion matrix and evaluation stats
library(caret)
rf_CM <- confusionMatrix(as.factor(test_complete$pred_class),
as.factor(test_complete$train_class))
print(rf_CM)Tarea
- Explorar el módulo v.kcv
- Cómo se podría haber utilizado para separar los puntos etiquetados en training y test?
- Cuál es la diferencia entre dicho módulo y la separación que realizamos en R?
Dar una mirada a v.divide.training_validation
Gracias por su atención!!
